﻿using Furion;
using Furion.Authorization;
using Furion.DataEncryption;
using Furion.DynamicApiController;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Queer.Cache;
using Queer.Entity;
using Queer.Enum;
using Queer.IBusiness.OrganizationManage;
using Queer.IBusiness.SystemManage;
using Queer.Util;
using Queer.Util.Helper;
using Queer.Util.Model;
using System;
using System.Collections.Generic;
using System.IdentityModel.Tokens.Jwt;
using System.Linq;
using System.Threading.Tasks;

namespace Queer.Web.Area.Admin.HomeManage
{
    /// <summary>
    /// 登陆控制器（不验证权限）
    /// </summary>
    [ApiDescriptionSettings("Admin", SplitCamelCase = false)]
    [Route("HomeManage/[controller]")]
    [AllowAnonymous]
    public class LoginController : IDynamicApiController
    {
        private readonly IUserBLL _sysUserBLL;
        private readonly ILogLoginBLL _sysLogLoginBLL;
        private readonly OperatorCache _operatorCache;

        public LoginController(IUserBLL sysUserBLL, ILogLoginBLL sysLogLoginBLL, OperatorCache operatorCache)
        {
            _sysUserBLL = sysUserBLL;
            _sysLogLoginBLL = sysLogLoginBLL;
            _operatorCache = operatorCache;
        }

        /// <summary>
        /// 验证码
        /// </summary>
        [HttpPost]
        public TData<object> GetCaptchaImage()
        {
            Tuple<string, int> captchaCode = CaptchaHelper.GetCaptchaCode();
            byte[] bytes = CaptchaHelper.CreateCaptchaImage(captchaCode.Item1);
            string pic = Convert.ToBase64String(bytes);
            int result = captchaCode.Item2;

            TData<object> obj = new TData<object>();
            obj.Data = new { pic = pic, result = result };
            obj.Tag = 1;


            return obj;
        }

        /// <summary>
        /// 服务器端滑块验证方法
        /// </summary>
        [HttpPost]
        public TData<object> Captcha([FromForm] string datas)
        {
            List<int> fdatas = datas.ToObject<List<int>>();
            var sum = fdatas.Sum();
            var avg = sum * 1.0 / fdatas.Count;
            var stddev = fdatas.Select(v => Math.Pow(v - avg, 2)).Sum() / fdatas.Count;

            TData<object> obj = new TData<object>();
            obj.Data = (stddev != 0);
            obj.Tag = 1;
            return obj;
        }

        /// <summary>
        /// 用户登陆
        /// </summary>
        [HttpPost]
        public async Task<TData<OperatorInfo>> Login(string userName, string password)
        {
            TData<OperatorInfo> obj = new TData<OperatorInfo>();
            TData<UserEntity> userObj = await _sysUserBLL.CheckLogin(userName, password);
            if (userObj.Tag == 1)
            {
                await _operatorCache.AddCurrent(userObj.Data.ApiToken);
                obj.Data = await _operatorCache.Current(userObj.Data.ApiToken);
            }

            string ip = NetHelper.Ip;
            string browser = NetHelper.Browser;
            string os = NetHelper.GetOSVersion();
            string userAgent = NetHelper.UserAgent;

            LogLoginEntity logLoginEntity = new LogLoginEntity
            {
                LogStatus = userObj.Tag == 1 ? OperateStatusEnum.Success.ParseToInt() : OperateStatusEnum.Fail.ParseToInt(),
                Remark = userObj.Message,
                IpAddress = ip,
                IpLocation = IpLocationHelper.GetIpLocation(ip),
                Browser = browser,
                OS = os,
                ExtraRemark = userAgent,
                LoginUser = userName,
                LoginTime = DateTime.Now
            };

            await _sysLogLoginBLL.SaveForm(logLoginEntity);

            obj.Tag = userObj.Tag;
            obj.Message = userObj.Message;

            if (userObj.Tag == 0)
                return obj;

            // 生成前端的token
            var jwtSettings = App.GetOptions<JWTSettingsOptions>();
            var datetimeOffset = DateTimeOffset.UtcNow;

            // 修改过期时间
            jwtSettings.ExpiredTime = GlobalContext.SystemConfig.UserExpiredTime;

            var accessToken = JWTEncryption.Encrypt(jwtSettings.IssuerSigningKey, new Dictionary<string, object>()
                            {
                                { "UserId", userObj.Data.Id.ToString() },  // 存储Id
                                { "Account",userObj.Data.UserName }, // 存储用户名
                                { "ApiToken",userObj.Data.ApiToken }, // ApiToken
                                { JwtRegisteredClaimNames.Iat, datetimeOffset.ToUnixTimeSeconds() },
                                { JwtRegisteredClaimNames.Nbf, datetimeOffset.ToUnixTimeSeconds() },
                                { JwtRegisteredClaimNames.Exp, DateTimeOffset.UtcNow.AddSeconds(jwtSettings.ExpiredTime.Value*60).ToUnixTimeSeconds() },
                                { JwtRegisteredClaimNames.Iss, jwtSettings.ValidIssuer},
                                { JwtRegisteredClaimNames.Aud, jwtSettings.ValidAudience }
                            });

            // 覆盖apitoken，因为前端需要的是jwt生成的token，而缓存使用的是数据库的apitoken字段
            obj.Data.JwtToken = accessToken;

            return obj;
        }

        /// <summary>
        /// 获取当前登录用户信息
        /// </summary>
        [HttpGet]
        public async Task<TData<OperatorInfo>> GetAccessUserData()
        {
            OperatorInfo user = await _operatorCache.Current();
            TData<OperatorInfo> obj = new TData<OperatorInfo>();
            obj.Data = user;
            obj.Tag = 1;
            return obj;
        }
    }
}